package org.example;

import cn.hutool.core.lang.Console;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.RandomUtil;
import org.openqa.selenium.*;
import org.openqa.selenium.By.ByTagName;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.interactions.Actions;

import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

import static cn.hutool.core.text.CharSequenceUtil.format;
import static java.time.LocalDateTime.now;

public class Main {

    public static final  long      fixMillis    = 70_000;
    public static final  long      randomMillis = 70_000;
    private static final WebDriver WD;

    static {
        {
            System.setProperty("webdriver.chrome.driver", ".\\chromedriver-win64\\chromedriver.exe");
            ChromeOptions options = new ChromeOptions();
            options.addArguments("--remote-allow-origins=*");
            options.setAcceptInsecureCerts(true);
            WD = new ChromeDriver(options);
        }
    }

    private static final AtomicInteger charCount = new AtomicInteger(0);

    public static void main(String[] args) throws Exception {
        doLogin();
        hi();
    }

    public static void hi() throws InterruptedException {
        toSearchPage();
        try {
            if (hourBetween(now())) {
                doHi();
            }
            Thread.sleep(fixMillis + RandomUtil.randomLong(randomMillis));
        }
        catch (Exception e) {
            Console.error(e);
        }
        finally {
            hi();
        }
    }

    public static void doLogin() throws InterruptedException {
        WD.get("https://www.zhipin.com/web/user");

        // 用户需要在这两分钟内完成登录打开岗位查询页面
        int time    = 0;
        int timeOut = 1000 * 40;
        while (time < timeOut) {
            Thread.sleep(1000);
            time += 1000;
            Console.log("程序将在" + (timeOut - time) / 1000 + "秒后开启自动沟通，请打开岗位页面");
        }

        Console.log("自动沟通开始...");
    }

    public static void setNavigatorWebdriverUndefined() {
        JavascriptExecutor executor = (JavascriptExecutor) WD;
        String             script   = "navigator.webdriver=undefined";  // 获取页面标题的JavaScript代码

        executor.executeScript(script);
    }

    static final String[] CITIES;

    static {
        final String
                shanghaiCode = "101020100",
                nanjingCode = "101190100",
                wuxiCode = "101190200",
                suzhouCode = "101190400";

        CITIES = new String[]{ shanghaiCode, suzhouCode, nanjingCode, wuxiCode, wuxiCode };
    }

    public static void toSearchPage() throws InterruptedException {
        String randomCityCode = CITIES[RandomUtil.randomInt(CITIES.length)];
        WD.navigate()
          .to(format("https://www.zhipin.com/web/geek/job?query=java&city={}&salary={}{}", randomCityCode,
                     getSalary(), getDegree()));
        setNavigatorWebdriverUndefined();

        Thread.sleep(fixMillis + RandomUtil.randomLong(randomMillis));
    }

    public static String getSalary() {
        // 薪资10-20k 405
        // 薪资29-50k 406
        return "405";
    }

    public static String getDegree() {
        //return "&degree=202";
        return RandomUtil.randomInt(10) < 6 ? "&degree=202" : "";
    }

    public static boolean hourBetween(LocalDateTime time) {
        int hour = time.getHour();
        return hour >= 8 && hour <= 21;
        //return true;
    }

    public static void doHi() throws InterruptedException {
        System.err.println(LocalTime.now() + "," + charCount.incrementAndGet());
        Thread.sleep(2_000);
        List<WebElement> jobCards = WD.findElements(By.className("card-area"));
        if (jobCards.isEmpty()) {
            System.err.println("职位卡片为空");
        }

        for (WebElement jobCard : jobCards) {
            click(jobCard);

            try {
                Thread.sleep(2_000);
                String           bossName  = jobCard.findElement(By.className("boss-name")).getText();
                String           jobName   = WD.findElement(By.className("job-detail-info")).getText();
                WebElement       jobDetail = WD.findElement(By.className("job-detail-op"));
                List<WebElement> as        = jobDetail.findElements(ByTagName.tagName("a"));
                if (as.isEmpty() || illegalBossName(bossName) || illegalJobName(jobName) || !legalLabel()) {
                    continue;
                }
                WebElement element = as.get(1);
                Thread.sleep(3_000);
                click(element);
                Thread.sleep(2_000);
                chatBlock();
                stay();
            }
            catch (Exception e) {
                System.err.println(e);
            }
        }
    }

    public static boolean legalLabel() {
//        List<WebElement> labels = WD.findElement(By.className("job-label-list")).findElements(By.tagName("li"));
//
//        boolean java = false,
//                spring = false;
//        for (WebElement label : labels) {
//            java   |= containsIgnoreCase(label.getText(), "java");
//            spring |= containsIgnoreCase(label.getText(), "spring");
//        }
//
//        return java || spring;
        return true;
    }

    public static void chatBlock() throws InterruptedException {
        try {
            String text = WD.findElement(By.className("chat-block-body")).getText();
            if (CharSequenceUtil.isNotBlank(text)) {
                Thread.sleep(TimeUnit.HOURS.toMillis(1));
            }
        }
        catch (NoSuchElementException e) {

        }
    }

    public static void stay() {
        WebElement stayButton = WD.findElement(By.className("greet-boss-footer")).findElements(By.tagName("a")).get(0);
        click(stayButton);
    }

    public static void click(WebElement element) {
        new Actions(WD).moveToElement(element).perform();
        if (element != null) element.click();
    }

    private static boolean illegalJobName(String jobName) {
        String[] excludes = { "安卓", "某", "月", "Android", "android", "半年", "天", "测试", "实施", "兼职", "鸿蒙", "半年", "6个月",
                              "游戏", "Unity" };
        for (String exclude : excludes) {
            if (jobName.contains(exclude)) {
                return true;
            }
        }
        return false;
    }

    private static boolean illegalBossName(String bossName) {
        String[] excludes = { "某", "华为" };
        for (String exclude : excludes) {
            if (bossName.contains(exclude)) {
                return true;
            }
        }
        return false;
    }


}
